package common

import (
	"errors"
	"fmt"
	"github.com/mitchellh/go-homedir"
	"github.com/sirupsen/logrus"
	"github.com/spf13/viper"
	"io"
	"os"
	"strings"
	"time"
)

const (
	GlobalDefaultConfigPath = "~/migration-config.yaml"

	// 因为gitee限流，所以默认最大并发库为10个
	// 当执行mr和issue时，ignoreLimiting设置为false，打开限流
	// 当执行其他数据时，可以主动打开ignoreLimiting为true，忽略gitee的限流
	// 配置文件默认ignoreLimiting为false
	DefaultMaxParallelRepo               int = 10
	DefaultIgnoreLimitingMaxParallelRepo int = 500
)

type AlignedFormatter struct{}

func (f *AlignedFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	tm := entry.Time.Format(time.DateTime)
	level := fmt.Sprintf("%5s", entry.Level.String())
	message := fmt.Sprintf("[%s] [%s] msg=\"%s\"\n", tm, level, entry.Message)
	return []byte(message), nil
}

// NewLog
// filePath : /User/xxx/xx/x/a.log   or ~/xxx/xx/x/a.log
func NewLog(filePath string) (log *logrus.Logger, err error) {
	lastIdx := strings.LastIndex(filePath, "/")
	logFileName := filePath[lastIdx:]
	logFilePath := filePath[0:lastIdx]

	if logFilePath, err = homedir.Expand(logFilePath); err != nil {
		return
	}

	if err = os.MkdirAll(logFilePath, os.ModePerm); err != nil {
		return
	}

	log = logrus.New()
	logFile, err := os.OpenFile(logFilePath+"/"+logFileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
	if err != nil {
		return
	}
	log.Out = logFile
	log.SetFormatter(&AlignedFormatter{})
	log.Info("日志初始化成功")
	return
}

// NewGlobalLog 创建全局日志，向标准输出和文件输出
// filePath : /User/xxx/xx/x/global.log   or ~/xxx/xx/x/global.log
func NewGlobalLog(filePath string) (log *logrus.Logger, err error) {
	lastIdx := strings.LastIndex(filePath, "/")
	logFileName := filePath[lastIdx:]
	logFilePath := filePath[0:lastIdx]

	if logFilePath, err = homedir.Expand(logFilePath); err != nil {
		return
	}

	if err = os.MkdirAll(logFilePath, os.ModePerm); err != nil {
		return
	}

	log = logrus.New()
	logFile, err := os.OpenFile(logFilePath+"/"+logFileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
	if err != nil {
		return
	}
	log.SetOutput(io.MultiWriter(logFile, os.Stdout))
	log.SetFormatter(&AlignedFormatter{})
	log.Info("全局日志初始化成功")
	return
}

type Config struct {
	BaseConfig   BaseConfig `yaml:"baseConfig"`
	IncludeRepos []string   `yaml:"includeRepos"`
	ExcludeRepos []string   `yaml:"excludeRepos"`
	GlobalLog    *logrus.Logger
}

type BaseConfig struct {
	ExportPlatformName    string            `yaml:"exportPlatformName"`
	Token                 string            `yaml:"token"`
	EnterpriseToken       string            `yaml:"enterpriseToken"`
	EnterpriseName        string            `yaml:"enterpriseName"`
	ExportDataDir         string            `yaml:"exportDataDir"`
	MaxParallelRepoNum    int               `yaml:"maxParallelRepoNum"`
	MaxParallelFeatureNum int               `yaml:"maxParallelFeatureNum"`
	MaxWorkerNum          int               `yaml:"maxWorkerNum"`
	IgnoreLimiting        bool              `yaml:"ignoreLimiting"`  // 是否限制最大并发数，默认true。和maxParallelRepoNum配置使用
	RepoUseProgress       bool              `yaml:"repoUseProgress"` // 针对仓库是否使用进度功能，默认不使用
	TimeStamp             time.Time         `yaml:"timeStamp"`
	RoleMapping           map[string]string `yaml:"roleMapping"`
	Order                 map[string]int    `yaml:"order"`
	GlobalFeature         []string          `yaml:"globalFeature"`
	Feature               []string          `yaml:"feature"`
	RpcUrl                string            `yaml:"rpcUrl"`
	AppKey                string            `yaml:"appKey"`
	AppSecret             string            `yaml:"appSecret"`
	PageSize              int               // 固定为100，屏蔽用户的配置，为了提升效率，各个平台最大值均为100
	IncrementFlag         bool              // 是否执行增量导出，不来自yaml文件，来自命令行
	UseProgress           bool              // 不来自yaml文件，来自命令行，针对不分库任务，是否分库（获取仓库列表，label等待。。。）
	Export                bool              // 不来自yaml配置文件，来自命令行
	Check                 bool              // 不来自yaml文件，来自命令行，是否执行的是校验工作，而不是导出/导入工作
	Write                 bool              // 不来自yaml文件，来自check命令，true将导入失败的数据写入本地，默认false
}

func ParseConfig(path string) (config Config, err error) {
	if path, err = homedir.Expand(path); err != nil {
		return
	}
	_, err = os.Stat(path)
	if os.IsNotExist(err) {
		fmt.Println("配置文件不存在")
		return
	}

	vip := viper.New()
	vip.SetConfigFile(path)
	if err = vip.ReadInConfig(); err != nil {
		return
	}
	if err = vip.Unmarshal(&config); err != nil {
		return
	}

	if config.BaseConfig.ExportDataDir, err = homedir.Expand(config.BaseConfig.ExportDataDir); err != nil {
		return
	}

	// 屏蔽用户设置
	config.BaseConfig.PageSize = 100
	config.GlobalLog = nil

	if !config.BaseConfig.IgnoreLimiting && config.BaseConfig.MaxParallelRepoNum > DefaultMaxParallelRepo {
		config.BaseConfig.MaxParallelRepoNum = DefaultMaxParallelRepo
	} else if config.BaseConfig.IgnoreLimiting && config.BaseConfig.MaxParallelRepoNum > DefaultIgnoreLimitingMaxParallelRepo {
		config.BaseConfig.MaxParallelRepoNum = DefaultIgnoreLimitingMaxParallelRepo
	}

	if config.BaseConfig.EnterpriseName == "" {
		return config, errors.New("企业名称不能为空")
	}
	// 日期提前7天
	//config.BaseConfig.TimeStamp = config.BaseConfig.TimeStamp.Add(-7 * 24 * time.Hour)
	return
}
